package cn.niit.letuseatdemo.controller.user;

import cn.niit.letuseatdemo.common.enums.ExceptionCodeEnum;
import cn.niit.letuseatdemo.entity.domain.User;
import cn.niit.letuseatdemo.entity.vo.response.BaseResponse;
import cn.niit.letuseatdemo.service.UserService;
import cn.niit.letuseatdemo.util.H5LoginUtil;
import cn.niit.letuseatdemo.util.HttpUtils;
import cn.niit.letuseatdemo.util.RandomNumber;
import cn.niit.letuseatdemo.util.RedisUtil;
import com.google.code.kaptcha.impl.DefaultKaptcha;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Description  用户登陆注册控制器
 * vue界面的登录注册
 * @Author Zhang Shiqi
 * @CreateTime 2022/11/9 13:11
 */
@Slf4j
@RequestMapping("/api")
@RestController
public class UserLoginRegisterController {
    @Autowired
    private DefaultKaptcha captchaProducer;  //配置自动装配验证码的生成器
    @Autowired
    private UserService userService;

    @Autowired
    private RedisUtil redisUtil;

    /*
    * @Description: 验证码生成
    * @Author: Zhang Shiqi
    * @CreateTime： 2022/11/10 22:32
     * @param: request
     * @param: response
     * @return: cn.niit.letuseatdemo.entity.vo.response.BaseResponse
    **/
    //@CrossOrigin
    @GetMapping("/user/kaptcha")
    public BaseResponse kaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ByteArrayOutputStream imgOutputStream = new ByteArrayOutputStream();
        try {
            //获取上下文对象
            //ServletContext context = request.getServletContext();
            String uuid = UUID.randomUUID().toString();
            //生产验证码字符串并保存到session中
            String verifyCode = captchaProducer.createText();
            System.out.println("CommonController.defaultKaptcha 生成的图片验证码是：" + verifyCode);
            //1、获取当前会话的 session 对象；2、将图片验证码写入 session 中，供提交表单时验证。
            //request.getSession().setAttribute("verifyCode", verifyCode);//因为前后端分离项目，每次请求是不同的sesion，所以不能用session保存
            //context.setAttribute("verifycode-"+uuid, verifyCode);//需要在key里拼接uuid 把这个存到系统里面，然后要和下面的一模一样
            //通过 redisUtil 工具类实现数据的写入。
            redisUtil.set("verifyCode-" + uuid, verifyCode, RedisUtil.MINUTE_FIVE);

            BufferedImage challenge = captchaProducer.createImage(verifyCode);  //生成验证码图片
            ImageIO.write(challenge, "jpg", imgOutputStream);  //将验证码的图片格式输出为jpg

            Map<String, Object> map = new HashMap<>();
            map.put("uuid", uuid);//标识用户
            map.put("img", Base64.encode(imgOutputStream.toByteArray()));
            return BaseResponse.success(map);
        } catch (Exception e) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return BaseResponse.error("9003", "验证码获取失败");
        }
    }


    /*
    * @Description:发送短信验证码
    * @Author: Zhang Shiqi
    * @CreateTime： 2022/11/10 22:33
     * @param: request
     * @param: uuid
     * @param: verifyCode
     * @param: userTel
     * @return: cn.niit.letuseatdemo.entity.vo.response.BaseResponse
    **/
    // @CrossOrigin
    @GetMapping("/user/smscode") //请求地址： /api/user/smscode
    public  BaseResponse sendSmsCode(HttpServletRequest request,String uuid,String verifyCode,String userTel){
        log.info("用户发送短信验证码请求参数：uuid={},verifyCod={},userTel={}",uuid,verifyCode,userTel);
        //1、校验uuid. verifycode、userTel 是否为空?
        if(!StringUtils.hasLength(uuid)||!StringUtils.hasLength(verifyCode) || !StringUtils.hasLength(userTel)){
            log.error("errorMsg","请求参数uuid, verifycode, userTel不能为空!");
            return BaseResponse.error("90004","手机号、图片验证码不能为空！");
        }
        // 2、根据uuid 获取保存在上下文对象当中的系统验证码;
        //获取上下文对象
//        ServletContext context = request.getServletContext();
//        String kaptchaCode = context.getAttribute("verifycode-"+uuid)+"";
        String kaptchaCode = redisUtil.get("verifyCode-" + uuid) + "";
        //比较系统验证码与用广提交的验证码是否一致?
        if (!StringUtils.hasLength(kaptchaCode) || !verifyCode.equals(kaptchaCode)){
            log.error("errorMsg:图片验证码（{}）与系统图片验证码（{}）不正确！",verifyCode,kaptchaCode);
            return BaseResponse.error("90004",":图片验证码不正确！");
        }
        //发送短信; TODO
        //context.setAttribute("sms_code_register-"+uuid,"123456");
        //redisUtil.set("sms_code_register-" + uuid, "123456", RedisUtil.MINUTE_FIVE);
        String smsCode = RandomNumber.generateNumber(); //默认6位数字；
        String result = HttpUtils.sendSms(userTel, smsCode);  //发送短信验证码
        if(result.equals(HttpUtils.HTTP_RESPONSE_RESULT_SUCCESS)){
            redisUtil.set("sms_code_register-" + uuid, "123456", RedisUtil.MINUTE_FIVE);
            log.info("UUID={} 发送验证码：{}", uuid, smsCode);
            return BaseResponse.success();  //只需要告诉前端用户，短信验证码是否已发送
        }else{
            return BaseResponse.error(ExceptionCodeEnum.SMS_END_ERROR);
        }
       // return  BaseResponse.success();//只需要告诉前端用户，短信验证码是否已发送

    }

    /*
     * @Description: 用户注册
     * @Author: Zhang Shiqi
     * @CreateTime： 2022/11/10 22:39
     * @param: request
     * @param: user
     * @return: cn.niit.hospital.entity.vo.response.BaseResponse
     **/
    @PostMapping("/user/register")
    public BaseResponse register(HttpServletRequest request,@RequestBody User user){
        log.info("待注册的用户信息：{}",user);

        String uuid = user.getUuid(); //标识唯一用户内容uuid
        String verifyCode = user.getSmsCode(); //用户提交的短信验证码
        //1、校验参数是否为空?
        if(!StringUtils.hasLength(uuid)||!StringUtils.hasLength(verifyCode) || !StringUtils.hasLength(user.getUserTel())){
            log.error("errorMsg","请求参数uuid, verifycode, userTel不能为空!");
            return BaseResponse.error("90004","手机号、图片验证码不能为空！");
        }

        //获取上下文对象
        //ServletContext context = request.getServletContext();
        //2、获取系统【短信】验证码与用户提交到短信验证码
        //String smsCode= context.getAttribute("sms_code_register-"+uuid)+""; //获取系统中保存的短信验证码
        String smsCode = redisUtil.get("sms_code_register-" + uuid) + "";
        redisUtil.del("sms_code_register-" + uuid); //当短信验证码读取使用后，将Redis缓存中的验证码给删除。
        //3\比较系统验证码与用广提交的验证码是否一致?
        if (!StringUtils.hasLength(smsCode) || !verifyCode.equals(smsCode)){
            log.error("errorMsg:图片验证码（{}）与系统图片验证码（{}）不正确！",verifyCode,smsCode);
            return BaseResponse.error("90004",":图片验证码不正确！");
        }

        //4.将注册信息插入数据库，完成注册功能
        boolean result= userService.register(user);
        if(result){
            return BaseResponse.success();
        }
        return BaseResponse.error("90009","系统异常，注册失败");
    }

    /*
     * @Description: 用户登录
     * @Author: Zhang Shiqi
     * @CreateTime： 2022/11/11 21:20
     * @param: request
     * @param: user
     * @return: cn.niit.hospital.entity.vo.response.BaseResponse
     **/
    @PostMapping("/user/login")
    public BaseResponse login(HttpServletRequest request,@RequestBody User user) {
        log.info("用户登录信息：{}", user);
        String userTel = user.getUserTel();
        String userPassword = user.getUserPassword();
        String uuid = user.getUuid(); //标识唯一用户内容uuid
        String verifyCode = user.getVerifyCode(); //用户提交的短信验证码
        //1.校验请求参数是否为空
        if (!StringUtils.hasLength(uuid)
                || !StringUtils.hasLength(verifyCode)
                || !StringUtils.hasLength(userPassword)
                || !StringUtils.hasLength(userTel)) {
            log.error("errorMsg: 请求参数uuid, verifycode, userTel,userPassword不能为空!");
            return BaseResponse.error("90004", "手机号、密码、图片验证码不能为空!");

        }
        //2.根据uuid获取保存在上下文对象当中的系统验证码;
        //获取上下文对象
        //ServletContext context = request.getServletContext();
        //String kaptchaCode = context.getAttribute("verifycode-" + uuid) + "";
        String kaptchaCode = redisUtil.get("verifyCode-" + uuid) + "";
        redisUtil.del("verifyCode-" + uuid); //当短信验证码读取使用后，将Redis缓存中的验证码给删除。
        //3:比较系统验证码与用户提交的验证码是否一致?
        if (!StringUtils.hasLength(kaptchaCode) || !verifyCode.equals(kaptchaCode)) {
            log.error("errorwsg:图片验证码（）与系统图片验证码（）不正确! ", verifyCode, kaptchaCode);
            return BaseResponse.error("90004", "图片验证码不正确!");

        }
        //4.校验用户账号、密码是否一致
        //boolean result = userService.login(user);
        user = userService.login(user);
//        if (result) {
//            String token = UUID.randomUUID().toString(); // 生用户登录的凭证(token），用户登录后的每次请求需要携带该凭证
//            context.setAttribute("token-" + token, user);//将token放入缓存 TODO 通过Redis实现
//            Map<String, Object> map = new HashMap<>();
//            map.put("token", token);//将token返回给用户;
//            return BaseResponse.success(map);
//
//        }
        if(null != user){
            //生用户登录的凭证（token），用户登录后的每次请求需要携带该凭证
            String token = UUID.randomUUID().toString();    //TODO 通过 JWT 生成 Token
//            context.setAttribute("token-" + token, user);   //将 token 放入缓存
            redisUtil.set("token-" + token, user, RedisUtil.HOUR_HALF);
            Map<String, Object> map = new HashMap<>();
            map.put("token", token);    //将 token 返回给用户；
            return BaseResponse.success(map);
        }
        return BaseResponse.error("90009", "系统异常登录失败");
    }

    /*
    * @Description: 获取用户个人信息接口
    * @Author: Zhang Shiqi
    * @CreateTime： 2022/12/1 0:05
     * @param: token
     * @return: cn.niit.letuseatdemo.entity.vo.response.BaseResponse
    **/
    //@GetMapping("/user/info")
    public BaseResponse userInfo(@RequestHeader("auth-token") String token){
        log.info("获取个人信息接口：" + token);
        //TODO 根据 token 获取真实的用户信息
        User user = (User) redisUtil.get("token-" + token);
//        user.setUserName("张三");
        return BaseResponse.success(user);
    }

    /*
    * @Description: 通过公共的用户登录工具类获取登录用户信息
    * @Author: Zhang Shiqi
    * @CreateTime： 2022/12/1 1:27
     * @return: cn.niit.letuseatdemo.entity.vo.response.BaseResponse
    **/
    @GetMapping("/user/info")
    public BaseResponse getUserInfo(){
        User user = H5LoginUtil.getLoginUser(); //通过公共的用户登录工具类获取登录用户信息  在service里想用登录信息，直接copy
        log.info("【H5LoginUtil】获取个人信息接口: user = {}", user);
        return BaseResponse.success(user);
    }




}
